import { Util as CommonUtil} from '@supermap/iclient-common/commontypes/Util';
import { Unit } from '@supermap/iclient-common/REST';
import { CartoCSS } from '@supermap/iclient-common/style/CartoCSS';
import { JSONFormat } from '@supermap/iclient-common/format/JSON';
import {StyleUtils} from '@supermap/iclient-ol/core/StyleUtils';
import {Util} from '@supermap/iclient-ol/core/Util';
import Observable from 'ol/Observable';
import Style from 'ol/style/Style';
import CircleStyle from 'ol/style/Circle';
import FillStyle from 'ol/style/Fill';
import StrokeStyle from 'ol/style/Stroke';
import Text from 'ol/style/Text';
/**
 * @class VectorTileStyles
 * @classdesc 矢量瓦片风格。
 * @category  Visualization VectorTile
 * @param {Object} options - 交互时所需可选参数。
 * @extends {ol.Observable}
 * @usage
 */
export class VectorTileStyles extends Observable {

    constructor(options) {
        super();
        if (!options) {
            return;
        }
        var that = this;
        this.customSelectedStyle = null;//自定义选择要素样式
        this.customStyleFunction = null;//自定义要素函数
        if (options.donotNeedServerCartoCss !== undefined) {
            setDonotNeedServerCartoCss(options.donotNeedServerCartoCss);
        }
        if (options.view) {
            setView(options.view);
        }
        if (options.url) {
            setUrl(options.url);
        }
        if (options.cartoCss) {
            setCartoCss(options.cartoCss);
        }
        var selectedPointStyle = getDefaultSelectedPointStyle();
        if (options.selectedPointStyle) {
            selectedPointStyle = options.selectedPointStyle;
        }
        setSelectedPointStyle(selectedPointStyle);
        var selectedLineStyle = getDefaultSelectedLineStyle();
        if (options.selectedLineStyle) {
            selectedLineStyle = options.selectedLineStyle;
        }
        setSelectedLineStyle(selectedLineStyle);
        var selectedRegionStyle = getDefaultSelectedRegionStyle();
        if (options.selectedRegionStyle) {
            selectedRegionStyle = options.selectedRegionStyle;
        }
        setSelectedRegionStyle(selectedRegionStyle);
        var selectedTextStyle = getDefaultSelectedTextStyle();
        if (options.selectedTextStyle) {
            selectedTextStyle = options.selectedTextStyle;
        }
        setSelectedTextStyle(selectedTextStyle);
        var layersXHR = new XMLHttpRequest();
        layersXHR.onreadystatechange = function () {
            if (layersXHR.readyState == 4) {
                var result = JSON.parse(layersXHR.responseText);
                var layersInfo = {};
                for (var i = 0, len = result.length; i < len; i++) {
                    var layers = result[i].subLayers.layers;
                    for (var j = 0, len1 = layers.length; j < len1; j++) {
                        layers[j].layerIndex = len1 - j;
                        layersInfo[layers[j].name] = layers[j];
                    }
                }
                setLayersInfo(layersInfo);
                if (!getDonotNeedServerCartoCss()) {
                    var vectorStylesXHR = new XMLHttpRequest();
                    vectorStylesXHR.open("GET", CommonUtil.urlPathAppend(getUrl(), "tileFeature/vectorstyles.json"), false);
                    vectorStylesXHR.onreadystatechange = function () {
                        if (vectorStylesXHR.readyState == 4) {
                            var vectorStyles = new JSONFormat().read(vectorStylesXHR.responseText);
                            var cartoCss;
                            if (vectorStyles.style && vectorStyles.type === 'cartoCSS') {
                                cartoCss = vectorStyles.style;
                                cartoCss = cartoCss.replace(/[@]/gi, "___");
                                cartoCss = cartoCss.replace(/\\#/gi, "___");
                                //替换一些关键符号
                                var cachedLayer = {};
                                layersInfo && Object.keys(layersInfo).sort().forEach(function (attr) {
                                    var newAttr = attr.replace(/[@#\s]/gi, "___");
                                    var to = attr;
                                    var keys = Object.keys(cachedLayer);
                                    for (let index = keys.length; index > -1; index--) {
                                        if (attr.indexOf(keys[index]) > -1) {
                                            to = attr.replace(keys[index], cachedLayer[keys[index]]);
                                            break;
                                        }
                                    }
                                    to = to.replace(/[#]/gi, "\#");
                                    cachedLayer[attr] = newAttr;
                                    cartoCss = cartoCss.replace(new RegExp(to, "g"), newAttr);
                                })
                                cartoCss = cartoCss.replace(/[#]/gi, "\n#");
                                //将zoom转化为scale，以免引起混淆
                                cartoCss = cartoCss.replace(/\[zoom/gi, "[scale");
                            }
                            var cartoShadersArray = new CartoCSS(cartoCss).getShaders();
                            var cartoShaders = {};
                            cartoShadersArray.forEach(function (cartoShader) {
                                cartoShaders[cartoShader.elements[0].clean] = cartoShaders[cartoShader.elements[0].clean] || {};
                                cartoShaders[cartoShader.elements[0].clean][cartoShader.attachment] = cartoShaders[cartoShader.elements[0].clean][cartoShader.attachment] || [];
                                cartoShaders[cartoShader.elements[0].clean][cartoShader.attachment].push(cartoShader);
                                return cartoShader;
                            });
                            setCartoShaders(cartoShaders);
                        }
                    };
                    vectorStylesXHR.send(null);
                }
                if (getCartoCss()) {
                    var clientCartoShadersArray = new CartoCSS(getCartoCss()).getShaders();
                    var clientCartoShaders = {};
                    clientCartoShadersArray.forEach(function (cartoShader) {
                        clientCartoShaders[cartoShader.elements[0].clean] = clientCartoShaders[cartoShader.elements[0].clean] || {};
                        clientCartoShaders[cartoShader.elements[0].clean][cartoShader.attachment] = clientCartoShaders[cartoShader.elements[0].clean][cartoShader.attachment] || [];
                        clientCartoShaders[cartoShader.elements[0].clean][cartoShader.attachment].push(cartoShader);
                        return cartoShader;
                    });
                    setClientCartoShaders(clientCartoShaders);
                }
            }
        };
        layersXHR.open("GET", CommonUtil.urlPathAppend(getUrl(), "layers.json"), false);
        layersXHR.send(null);

        /**
         * @function VectorTileStyles.prototype.getDefaultSelectedPointStyle
         * @description 设置默认选择后的点样式。
         */
        function getDefaultSelectedPointStyle() {
            return new Style({
                image: new CircleStyle({
                    radius: 5,
                    fill: new FillStyle({
                        color: 'blue'
                    })
                })
            })
        }

        /**
         * @function VectorTileStyles.prototype.getDefaultSelectedLineStyle
         * @description 设置默认选择后的线样式。
         */
        function getDefaultSelectedLineStyle() {
            return new Style({
                stroke: new StrokeStyle({
                    color: 'blue',
                    width: 3
                })
            })
        }

        /**
         * @function VectorTileStyles.prototype.getDefaultSelectedRegionStyle
         * @description 设置默认选择后的面样式。
         */
        function getDefaultSelectedRegionStyle() {
            return new Style({
                fill: new FillStyle({
                    color: [0, 0, 255, 0.5]
                }),
                stroke: new StrokeStyle({
                    color: 'blue',
                    width: 3
                })
            })
        }

        /**
         * @function VectorTileStyles.prototype.getDefaultSelectedTextStyle
         * @description 设置默认选择后的文本样式。
         */
        function getDefaultSelectedTextStyle() {
            return new Style({
                text: new Text({
                    font: '15px Microsoft YaHei',
                    fill: new FillStyle({
                        color: 'blue'
                    }),
                    stroke: new StrokeStyle({
                        color: 'white',
                        width: 1
                    })
                })
            });
        }

        /**
         * @function VectorTileStyles.setCartoShaders
         * @description 设置服务端 Carto 的阴影。
         * @param {Array} cartoShaders - 服务端 Carto 阴影。
         */
        function setCartoShaders(cartoShaders) {
            that.cartoShaders = cartoShaders;
        }

        /**
         * @function VectorTileStyles.getCartoShaders
         * @description 获取服务端 Carto 的阴影。
         */
        function getCartoShaders() {
            return that.cartoShaders;
        }

        /**
         * @function VectorTileStyles.setClientCartoShaders
         * @description 设置客户端 Carto 的阴影。
         * @param {Array} clientCartoShaders - 客户端 Carto 阴影。
         */
        function setClientCartoShaders(clientCartoShaders) {
            that.clientCartoShaders = clientCartoShaders;
        }

        /**
         * @function VectorTileStyles.getClientCartoShaders
         * @description 获取客户端 Carto 的阴影。
         */
        function getClientCartoShaders() {
            return that.clientCartoShaders;
        }

        /**
         * @function VectorTileStyles.setCartoCss
         * @description 设置 cartoCss 的样式。
         * @param {Object} cartoCss - cartoCss 的样式。
         */
        function setCartoCss(cartoCss) {
            that.cartoCss = cartoCss;
        }

        /**
         * @function VectorTileStyles.getCartoCss
         * @description 获取 cartoCss 的样式。
         */
        function getCartoCss() {
            return that.cartoCss;
        }

        /**
         * @function VectorTileStyles.setDonotNeedServerCartoCss
         * @description 设置是否需要 CartoCss 服务。
         * @param {Object} donotNeedServerCartoCss - 是否需要 CartoCss 服务。
         */
        function setDonotNeedServerCartoCss(donotNeedServerCartoCss) {
            that.donotNeedServerCartoCss = donotNeedServerCartoCss;
        }

        /**
         * @function VectorTileStyles.getDonotNeedServerCartoCss
         * @description 获取是否需要 CartoCss 服务。
         */
        function getDonotNeedServerCartoCss() {
            return that.donotNeedServerCartoCss;
        }

        /**
         * @function VectorTileStyles.setLayersInfo
         * @description 设置图层信息服务。
         * @param {Object} layersInfo - 图层信息。
         */
        function setLayersInfo(layersInfo) {
            that.layersInfo = layersInfo;
        }

        /**
         * @function VectorTileStyles.getLayersInfo
         * @description 获取图层信息服务。
         */
        function getLayersInfo() {
            return that.layersInfo;
        }

        /**
         * @function VectorTileStyles.setUrl
         * @description 设置地址。
         * @param {string} url - 地址。
         */
        function setUrl(url) {
            that.url = url;
        }

        /**
         * @function VectorTileStyles.getUrl
         * @description 获取地址。
         */
        function getUrl() {
            return that.url;
        }

        /**
         * @function VectorTileStyles.setView
         * @description 设置视图。
         * @param {Object} view - 视图。
         */
        function setView(view) {
            that.view = view;
        }

        /**
         * @function VectorTileStyles.getView
         * @description 获取视图。
         */
        function getView() {
            return that.view;
        }

        /**
         * @function VectorTileStyles.setFieldId
         * @description 设置主键ID字段名。
         * @param {number} fieldId - 主键ID字段名。
         */
        function setFieldId(fieldId) {
            that.fieldId = fieldId;
        }

        /**
         * @function VectorTileStyles.getFieldId
         * @description 获取主键ID字段名。
         */
        function getFieldId() {
            return that.fieldId;
        }

        /**
         * @function VectorTileStyles.setSelectedId
         * @description 设置选择序号。
         * @param {number} selectedId - 选择序号。
         */
        function setSelectedId(selectedId) {
            that.selectedId = selectedId;
        }

        /**
         * @function VectorTileStyles.getSelectedId
         * @description 获取选择序号。
         */
        function getSelectedId() {
            return that.selectedId;
        }

        /**
         * @function VectorTileStyles.setLayerName
         * @description 设置图层名称。
         * @param {string} layerName - 图层名称。
         */
        function setLayerName(layerName) {
            that.layerName = layerName;
        }

        /**
         * @function VectorTileStyles.getLayerName
         * @description 获取图层名称。
         */
        function getLayerName() {
            return that.layerName;
        }

        /**
         * @function VectorTileStyles.setSelectedPointStyle
         * @description 设置选择后点样式。
         * @param {Object} selectedPointStyle - 选择后点样式。
         */
        function setSelectedPointStyle(selectedPointStyle) {
            that.selectedPointStyle = selectedPointStyle;
        }

        /**
         * @function VectorTileStyles.setSelectedLineStyle
         * @description 设置选择后线样式。
         * @param {Object} selectedLineStyle - 选择后线样式。
         */
        function setSelectedLineStyle(selectedLineStyle) {
            that.selectedLineStyle = selectedLineStyle;
        }

        /**
         * @function VectorTileStyles.setSelectedRegionStyle
         * @description 设置选择后面样式。
         * @param {Object} selectedRegionStyle - 选择后面样式。
         */
        function setSelectedRegionStyle(selectedRegionStyle) {
            that.selectedRegionStyle = selectedRegionStyle;
        }

        /**
         * @function VectorTileStyles.setSelectedTextStyle
         * @description 设置选择后文本样式。
         * @param {Object} selectedTextStyle - 选择后文本样式。
         */
        function setSelectedTextStyle(selectedTextStyle) {
            that.selectedTextStyle = selectedTextStyle;
        }

        /**
         * @function VectorTileStyles.getSelectedStyle
         * @description 设置选择后的样式。
         * @param {string} type - 选择后的样式。
         */
        function getSelectedStyle(type) {
            if (type === 'POINT' || type === 'MULTIPOINT') {
                return that.selectedPointStyle;
            }
            if (type === 'LINESTRING' || type === 'MULTILINESTRING') {
                return that.selectedLineStyle;
            }
            if (type === 'POLYGON' || type === 'MULTIPOLYGON') {
                return that.selectedRegionStyle;
            }
            //zyt--文本不选中
            /*if (type === 'TEXT') {
                return that.selectedTextStyle;
            }*/
            return null;
        }

        /**
         * @function VectorTileStyles.getLayerInfo
         * @description 获取图层的信息。
         * @param {string} layerName - 图层名。
         */
        function getLayerInfo(layerName) {
            debugger;
            var layersInfo = getLayersInfo();
            if (layersInfo === undefined) {
                return null;
            }
            var layerInfo = layersInfo[layerName];
            if (!layerInfo) {
                return null;
            }
            var layerInfo_simple = {layerIndex: layerInfo.layerIndex, ugcLayerType: layerInfo.ugcLayerType};
            switch (layerInfo.ugcLayerType) {
                case "VECTOR":
                    layerInfo_simple.layerStyle = layerInfo.style ? layerInfo.style : null;
                    break;
                case "THEME":
                    var theme = layerInfo.theme;
                    layerInfo_simple.layerStyle = theme ? theme.defaultStyle : null;
                    if (theme && theme.type === "LABEL") {
                        layerInfo_simple.type = theme.type;
                        layerInfo_simple.textField = theme.labelExpression;
                    }
                    break;
                default :
                    //SVTile发布出来的地图没有ugcLayerType属性
                    if (layerInfo.style) {
                        layerInfo_simple.layerStyle = layerInfo.style;
                    }
                    break;
            }
            return layerInfo_simple;
        }

        /**
         * @function VectorTileStyles.getStyle
         * @description 获取样式。
         * @param {string} originalLayerName - 原始图层信息。
         * @param {Object} feature - 要素对象。
         */
        function getStyle(originalLayerName, feature) {
            debugger
            var url = getUrl(),
                view = getView(),
                zoom = view.getZoom(),
                dpi = 96,
                // dpi = 90.7142857142857,//自定义比例尺
                // dpi = 90.71,//自定义比例尺
                scale = Util.resolutionToScale(view.getResolution(), dpi, Unit.DEGREE),
                layerName = originalLayerName.replace(/(@)/gi, '___').replace(/(#)/gi, '___');
            // feature对象样式的配置遵循以下优先级：
            // 客户端CartoCSS > 服务器端CartoCSS > 服务器端layer样式 > 客户端默认样式。
            if (getCartoCss() && getClientCartoShaders()[layerName]) {
                return getStyleArray(getClientCartoShaders()[layerName]);
            }
            var layerInfo = getLayerInfo(originalLayerName);
            if (!getDonotNeedServerCartoCss() && getCartoShaders()[layerName]) {
                //zyt--不显示文字图层
                if(originalLayerName.indexOf("#")!=-1){
                    return null;
                }
                //如果是文本，这里特殊处理。
                if (feature.getProperties().textStyle || feature.getProperties().TEXT_FEATURE_CONTENT || layerInfo.type == 'LABEL' && layerInfo.textField) {
                    var featureStyle = StyleUtils.getValidStyleFromLayerInfo(layerInfo, feature, url);
                    if (feature.getGeometry().getType().toUpperCase() === "POINT") {
                        featureStyle = mergeTextFeatureStyle(layerInfo, feature, url);
                    }

                    return featureStyle;
                }
                return getStyleArray(getCartoShaders()[layerName]);
            }
            if (layerInfo) {
                return StyleUtils.getValidStyleFromLayerInfo(layerInfo, feature, url);
            }

            function getStyleArray(shaderAttachment) {
                var styleArray = [];
                for (var j in shaderAttachment) {
                    shaderAttachment[j].map(function (shader) {
                        styleArray.push(StyleUtils.getStyleFromCarto(zoom, scale, shader, feature, true, url))
                        return shader;
                    })
                }
                return styleArray;
            }

            /**
             * @function VectorTileStyles.prototype.mergeTextFeatureStyle
             * @description 合并文本要素样式。
             * @param {string} layerInfo - 图层信息。
             * @param {Object} feature - 获取的要素。
             * @param {string} url - 服务地址。
             */
            function mergeTextFeatureStyle(layerInfo, feature, url) {
                var textFeatureStyle = StyleUtils.getValidStyleFromLayerInfo(layerInfo, feature, url);
                if (layerInfo.type == 'LABEL') {
                    feature.setProperties({type: "TEXT"});
                    var cartoTextStyles = getStyleArray(getCartoShaders()[layerName]);
                    var textStyle = textFeatureStyle.getText();
                    for (var i = 0; i < cartoTextStyles.length; i++) {
                        if (!textStyle) {
                            textStyle = cartoTextStyles[i].getText();
                        } else {
                            textStyle.setText(cartoTextStyles[i].getText().getText());
                        }
                    }
                    textFeatureStyle.setText(textStyle);
                    return textFeatureStyle;
                }
                return textFeatureStyle;
            }

        }

        /**
         * @function VectorTileStyles.prototype.setCustomStyle
         * @description 设置自定义样式。
         * @param {Object} customStylesObj - 自定义样式。
         */
        this.setCustomStyleFuntion = function setCustomStyle(customStylesObj) {
            if(customStylesObj){
                if(customStylesObj.selectedStyle!=undefined){//自定义选择要素样式
                    that.customSelectedStyle = customStylesObj.selectedStyle;
                }
                if(customStylesObj.customStyleFunction!=undefined){//自定义要素样式函数
                    that.customStyleFunction = customStylesObj.customStyleFunction;
                }
            }
        }

        /**
         * @function VectorTileStyles.prototype.getFeatureStyle
         * @description 获取要素样式。
         * @param {Object} feature - 要素。
         */
        this.featureStyleFuntion = function getFeatureStyle(feature) {
            debugger;
            var selectedStyle;
            var layerName = feature.getProperties().layerName || feature.getProperties().layer;
            var id = feature.getProperties().id || parseInt(feature.getProperties().SmID);
            if (feature.getProperties().type && feature.getProperties().type.toUpperCase() === 'TEXT') {
                //zyt--文本不选中
                /*selectedStyle = getSelectedStyle(feature.getProperties().type.toUpperCase());
                if (feature.getProperties().texts) {
                    selectedStyle.getText().text_ = feature.getProperties().texts[0];
                } else {
                    selectedStyle.getText().text_ = "";
                }*/
            } else {
                selectedStyle = getSelectedStyle(feature.getGeometry().getType().toUpperCase());
            }
            if(that.customSelectedStyle!=null){//自定义选择要素样式
                selectedStyle = that.customSelectedStyle;
            }
            if (selectedStyle) {
                var selectedLayerName = getLayerName();
                var selectedId = getSelectedId();
                var fieldId = getFieldId();//获取主键ID字段名
                id = feature.getProperties().attributes[fieldId];
                if (selectedLayerName === layerName && id === selectedId) {
                    return selectedStyle;
                }
            }

            if(that.customStyleFunction!=null) {//自定义要素样式函数
                let customStyle = that.customStyleFunction(feature);
                if(customStyle){
                    return customStyle;
                }
            }
            console.log(feature.getProperties().type.toUpperCase());
            //zyt--不显示矢量要素
            if(feature.getProperties().type.toUpperCase()=="POINT"){
                return new Style({
                    image: new CircleStyle({
                        radius: 1,
                        fill: new FillStyle({
                            color: 'rgba(0,0,0,0.1)'
                        })
                    }),
                });
            }else if(feature.getProperties().type.toUpperCase()=="LINE"){
                return new Style({
                    stroke: new StrokeStyle({
                        color: "rgba(0,0,0,0.1)",
                        width: 1,
                    }),
                });
            }else if(feature.getProperties().type.toUpperCase()=="REGION"){
                return new Style({
                    stroke: new StrokeStyle({
                        color: "rgba(0,0,0,0.1)",
                        width: 1,
                    }),
                    fill: new FillStyle({
                        color: "rgba(0,0,0,0)",
                    }),
                });
            }

            return getStyle(layerName, feature);
        }

        /**
         * @function VectorTileStyles.prototype.featureSelectedFunction
         * @description 设置选中要素信息。
         * @param {Object} obj - 选中要素信息。
         */
        this.featureSelectedFunction = function (obj) {
            setSelectedId(obj.selectedId);
            setLayerName(obj.layerName);
            setFieldId(obj.fieldId);
        }
    }
}
